/**
 * A Google Maps (v3) control that moves the map back and forth between a
 * pop-out window and where it was before. Currently works in Google Chrome,
 * other browsers not tested.
 *
 * @author Ruquay K Calloway
 * @copyright Bornemann AG 2013
 *
 * @param google.maps.Map
 * @param Object options specifications
 */
function PopoutControl(map, opts) {
    // window-naming function attached to class on first run
    if ( ! PopoutControl.uniq ) {
        PopoutControl.uniq = (function(){
            var ix = 0;
            return function() { return "PopoutControl-" + (++ix); }
        })();
    }

    // options & defaults
    this.options = ( opts = opts || {} );
    opts.name = opts.name || PopoutControl.uniq();
    opts.width = opts.width || 1024;
    opts.height = opts.height || 720;
    opts.popoutText = opts.popoutText || "POP-OUT";
    opts.popoutTitle = opts.popoutTitle || "Open map in a pop-up window";
    opts.popinText = opts.popinText || "POP-IN";
    opts.popinTitle = opts.popinTitle || "Put map back into main window";

    // reference for triggering the popout, popin events
    var self = this;

    // ghost div to ensure we re-insert at the correct place
    var divGhost = document.createElement("div");
    divGhost.style.display = "none";

    // a few references helpful for removal and reinsertion into the same spot
    var divMap = map.getDiv();
    var domParent = divMap.parentNode;
    var tResize = function(){ google.maps.event.trigger(map, "resize"); };
    var wOther = null;// other window
    var oCss = {};// original relevant CSS of divMap
    var isPoppingIn = null;// deals w/ multiple windows running parallel

    // create additional div for padding from the edge of the map
    var div = document.createElement("div");
    div.style.padding = "5px";
    this.getDiv = function(){ return div; }
    this.toggle = function(){ wOther ? popIn() : popOut(); }

    // Set CSS for the control border
    var divButton = document.createElement("div");
    div.appendChild(divButton);
    divButton.style.fontFamily = "Arial,sans-serif";
    divButton.style.fontWeight = "bold";
    divButton.style.fontSize = "13px";
    divButton.style.backgroundColor = "#FFFFFF";
    divButton.style.borderColor = "#717B87";
    divButton.style.borderStyle = "solid";
    divButton.style.borderWidth = "1px";
    divButton.style.padding = "1px 6px";
    divButton.style.cursor = "pointer";
    divButton.style.textAlign = "center";
    divButton.style.boxShadow = "rgba(0, 0, 0, 0.4) 0px 2px 4px";
    setMode("popout");// immediately set button to "popout" mode

    // set the popout/popin button to toggle
    google.maps.event.addDomListener(divButton, "click", this.toggle);
    
    function setMode(type) {
        divButton.title = opts[type + "Title"];
        divButton.innerHTML = opts[type + "Text"];
    }

    function popOut() {
        // see note by popIn()
        isPoppingIn = false;

        // initialize & style the window
        var spec = "height=" + opts.height + ",width= " + opts.width
            + ",modal=yes,alwaysRaised=yes,location=0";
        wOther = window.open("about:blank", opts.name, spec);
        wOther.document.body.style.height = "100%"
        wOther.document.body.style.width = "100%"
        wOther.document.body.style.margin = "0"
        wOther.document.body.style.padding = "0"

        // push the ghost div into the document so we know where to pop into
        domParent.insertBefore( divGhost, divMap );

        // keep track of old CSS width/height for popping back in
        oCss.height = divMap.style.height;
        oCss.width = divMap.style.width;
        // push the map node into the wOther window's body, resize it
        wOther.document.body.appendChild( divMap );
        divMap.style.height = "100%";
        divMap.style.width = "100%";

        // ensure the resize always gets triggered, keep handle for clearing
        google.maps.event.addDomListener(wOther, "resize", tResize);
        tResize();

        // set to pop-in mode
        setMode("popin");
        
        // closing the pop-up triggers same as clicking pop-in button
        wOther.onbeforeunload = popIn;

        // trigger the popout event on this control and give access to the window
        google.maps.event.trigger(self, "popout", wOther, divGhost);
    }

    // pops back into the original placeholder, closes the popped-out window
    function popIn() {
        // seems silly, but was the easiest way when calling
        // click/onbeforeunload for the same thing
        if ( isPoppingIn ){ return; } else { isPoppingIn = true; }

        // revert CSS rules
        divMap.style.height = oCss.height;
        divMap.style.width = oCss.width;

        // close popout window
        wOther.close();
        wOther = null;

        // pop the map back where it was, remove the divGhost again
        domParent.insertBefore( divMap, divGhost );
        domParent.removeChild( divGhost );

        // trigger the resize and the popin event
        tResize();
        google.maps.event.trigger(self, "popin", divGhost);

        // set button back to pop-out mode
        setMode("popout");
    }
}
